package org.dromara.patrol.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.PageUtils;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.patrol.domain.PatrolActionStatistics;
import org.dromara.patrol.domain.bo.PatrolActionQuery;
import org.dromara.patrol.domain.bo.PatrolActionStatisticsBo;
import org.dromara.patrol.domain.bo.StatisticsCountBo;
import org.dromara.patrol.domain.vo.*;
import org.dromara.patrol.mapper.PatrolActionStatisticsMapper;
import org.dromara.patrol.service.IPatrolActionStatisticsService;
import org.dromara.system.api.RemoteStoreService;
import org.dromara.system.api.domain.vo.RemoteStoreVo;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 巡店管理-巡店行为统计Service业务层处理
 *
 * @author han
 * @date 2024-04-19
 */
@RequiredArgsConstructor
@Service
public class PatrolActionStatisticsServiceImpl implements IPatrolActionStatisticsService {

    private final PatrolActionStatisticsMapper baseMapper;


    @DubboReference
    private RemoteStoreService remoteStoreService;


    /**
     * 查询巡店管理-巡店行为统计
     */
    @Override
    public PatrolActionStatisticsVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询巡店管理-巡店行为统计列表
     */
    @Override
    public TableDataInfo<PatrolActionStatisticsVo> queryPageList(PatrolActionStatisticsBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PatrolActionStatistics> lqw = buildQueryWrapper(bo);
        Page<PatrolActionStatisticsVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询巡店管理-巡店行为统计列表
     */
    @Override
    public List<PatrolActionStatisticsVo> queryList(PatrolActionStatisticsBo bo) {
        LambdaQueryWrapper<PatrolActionStatistics> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PatrolActionStatistics> buildQueryWrapper(PatrolActionStatisticsBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PatrolActionStatistics> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, PatrolActionStatistics::getUserId, bo.getUserId());
        lqw.eq(bo.getGroupId() != null, PatrolActionStatistics::getGroupId, bo.getGroupId());
        lqw.eq(bo.getStoreId() != null, PatrolActionStatistics::getStoreId, bo.getStoreId());
        lqw.eq(bo.getReportId() != null, PatrolActionStatistics::getReportId, bo.getReportId());
        lqw.eq(bo.getLastPatrolTime() != null, PatrolActionStatistics::getLastPatrolTime, bo.getLastPatrolTime());
        lqw.eq(bo.getScore() != null, PatrolActionStatistics::getScore, bo.getScore());
        lqw.eq(bo.getTotalScore() != null, PatrolActionStatistics::getTotalScore, bo.getTotalScore());
        lqw.eq(bo.getProblemNumber() != null, PatrolActionStatistics::getProblemNumber, bo.getProblemNumber());
        lqw.eq(bo.getCheckItemNumber() != null, PatrolActionStatistics::getCheckItemNumber, bo.getCheckItemNumber());
        lqw.eq(bo.getDuration() != null, PatrolActionStatistics::getDuration, bo.getDuration());
        lqw.eq(bo.getRectifyNumber() != null, PatrolActionStatistics::getRectifyNumber, bo.getRectifyNumber());
        lqw.eq(bo.getTaskPatrol() != null, PatrolActionStatistics::getTaskPatrol, bo.getTaskPatrol());
        lqw.eq(bo.getFreePatrol() != null, PatrolActionStatistics::getFreePatrol, bo.getFreePatrol());
        lqw.eq(bo.getRealTimePatrol() != null, PatrolActionStatistics::getRealTimePatrol, bo.getRealTimePatrol());
        lqw.eq(bo.getLivePatrol() != null, PatrolActionStatistics::getLivePatrol, bo.getLivePatrol());
        lqw.eq(bo.getVideoPatrol() != null, PatrolActionStatistics::getVideoPatrol, bo.getVideoPatrol());
        lqw.eq(bo.getTemplatePatrol() != null, PatrolActionStatistics::getTemplatePatrol, bo.getTemplatePatrol());
        lqw.eq(bo.getCustomPatrol() != null, PatrolActionStatistics::getCustomPatrol, bo.getCustomPatrol());
        lqw.eq(bo.getRectifyPass() != null, PatrolActionStatistics::getRectifyPass, bo.getRectifyPass());
        lqw.eq(bo.getNotApplicableNumber() != null, PatrolActionStatistics::getNotApplicableNumber, bo.getNotApplicableNumber());
        return lqw;
    }

    /**
     * 新增巡店管理-巡店行为统计
     */
    @Override
    public Boolean insertByBo(PatrolActionStatisticsBo bo) {
        PatrolActionStatistics add = MapstructUtils.convert(bo, PatrolActionStatistics.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改巡店管理-巡店行为统计
     */
    @Override
    public Boolean updateByBo(PatrolActionStatisticsBo bo) {
        PatrolActionStatistics update = MapstructUtils.convert(bo, PatrolActionStatistics.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PatrolActionStatistics entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除巡店管理-巡店行为统计
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 查询任务状态
     *
     * @param query
     * @return
     */
    @Override
    public TaskStatusVo selectTaskStatus(PatrolActionQuery query) {
        if (ObjectUtil.isNull(query)){
            throw new ServiceException("参数错误");
        }
        List<Long> groupIds = query.getGroupIds();
        if (CollectionUtils.isNotEmpty(groupIds)){
            List<RemoteStoreVo> remoteStoreVos = remoteStoreService.queryStoreByGroupIds(groupIds);
            List<Long> storeIds = remoteStoreVos.stream().map(RemoteStoreVo::getStoreId).collect(Collectors.toList());
            //区域下门店都没有,直接放回
            if (CollectionUtils.isEmpty(storeIds)){
                return new TaskStatusVo();
            }
            query.setStoreIds(storeIds);
        }

        return baseMapper.selectTaskStatus(query);
    }

    /**
     * 查询门店覆盖率
     *
     * @param query
     * @return
     */
    @Override
    public StoreCoverVo selectStoreCover(PatrolActionQuery query) {
        // 门店覆盖情况： 时间范围内，做了巡店的门店个数 / 总门店个数       20 / 100  = 20%  门店id去重  与租户和门店有查询关系
        //1.获取当前用户总门店,门店
        //2.获取时间范围内.做了巡店的门店
        return null;
    }

    /**
     * 查询已覆盖的门店
     *
     * @param query
     * @return
     */
    @Override
    public TableDataInfo<StoreCoverVo> selectStoreCovered(PatrolActionQuery query) {
        List<StoreCoverVo> storeCoverVos = baseMapper.selectStoreCoverPage(query);
        if (ObjectUtil.isNull(storeCoverVos)){
            return TableDataInfo.build();
        }
        List<Long> storeIds = StreamUtils.toSet(storeCoverVos, StoreCoverVo::getStoreId).stream().toList();
        Map<Long, String> storeMap = remoteStoreService.selectNamesByStoreList(storeIds);
        storeCoverVos.forEach(storeCoverVo -> {
            storeCoverVo.setStoreName(storeMap.get(storeCoverVo.getStoreId()));
        });
        TableDataInfo<StoreCoverVo> tableDataInfo = new TableDataInfo<>();
        tableDataInfo.setTotal(storeCoverVos.size());
        if (ObjectUtil.isNotNull(query.getPageSize()) || ObjectUtil.isNotNull(query.getPageNum())){
            storeCoverVos = PageUtils.getPageData(storeCoverVos, query.getPageNum() - 1, query.getPageSize());
        }
        tableDataInfo.setRows(storeCoverVos);
        return tableDataInfo;
    }

    /**
     * 查询未覆盖的门店
     *
     * @param query
     * @return
     */
    @Override
    public TableDataInfo<StoreCoverVo> selectStoreNotCovered(PatrolActionQuery query) {
        //1.获取区域,在处理人,但是不在这个巡店时间
        List<StoreCoverVo> storeNotCovered = baseMapper.selectStoreNotCovered(query);
        if (CollectionUtils.isNotEmpty(storeNotCovered)){
            List<Long> storeIds = StreamUtils.toSet(storeNotCovered, StoreCoverVo::getStoreId).stream().toList();
            Map<Long, String> storeMap = remoteStoreService.selectNamesByStoreList(storeIds);
            storeNotCovered.forEach(storeCoverVo -> {
                storeCoverVo.setStoreName(storeMap.get(storeCoverVo.getStoreId()));
            });
        }
        //2.获取全部的门店
        List<RemoteStoreVo> remoteStoreVos = remoteStoreService.queryStore();
        if (CollectionUtils.isNotEmpty(remoteStoreVos)) {
                List<StoreCoverVo> storeCovers = BeanUtil.copyToList(remoteStoreVos, StoreCoverVo.class);
                //过滤掉在上面集合中已经存在的
                List<StoreCoverVo> filteredStoreCovers = storeNotCovered;
                List<StoreCoverVo> finalStoreCoverVos = storeCovers.stream()
                        .filter(storeCover -> !filteredStoreCovers.stream()
                                .anyMatch(existingCover -> existingCover.getStoreId().equals(storeCover.getStoreId())))
                        .collect(Collectors.toList());
                storeNotCovered.addAll(finalStoreCoverVos);
            }
        List<StoreCoverVo> storeCoverVos = baseMapper.selectStoreCoverPage(query);
        //3.过滤掉已覆盖的门店
        storeNotCovered = storeNotCovered.stream()
                .filter(storeNotCoveredItem -> !storeCoverVos.stream()
                        .anyMatch(storeCoverVo -> storeCoverVo.getStoreId().equals(storeNotCoveredItem.getStoreId())))
                .collect(Collectors.toList());
        TableDataInfo<StoreCoverVo> tableDataInfo = new TableDataInfo<>();
        tableDataInfo.setTotal(storeNotCovered.size());
        if (ObjectUtil.isNotNull(query.getPageSize()) || ObjectUtil.isNotNull(query.getPageNum())){
            storeNotCovered = PageUtils.getPageData(storeNotCovered, query.getPageNum() - 1, query.getPageSize());
        }
        tableDataInfo.setRows(storeNotCovered);
        return tableDataInfo;
    }

    @Override
    public List<PatrolActionStatistics> selectList(StatisticsCountBo bo, StatisticsCountTimeVo timeVo) {
        LambdaQueryWrapper<PatrolActionStatistics> lqw = buildQueryWrapper(bo, timeVo);
        return baseMapper.selectList(lqw);
    }

    /**
     * 查询上周期和本周期的列表
     * @param query     条件
     * @param timeVo    周期时间
     * @return          列表
     */
    private LambdaQueryWrapper<PatrolActionStatistics> buildQueryWrapper(StatisticsCountBo query, StatisticsCountTimeVo timeVo) {
        LambdaQueryWrapper<PatrolActionStatistics> lqw = Wrappers.lambdaQuery();
        lqw.and(
                i -> i.between(PatrolActionStatistics::getLastPatrolTime, timeVo.getStartTime(), timeVo.getEndTime())
                        .or()
                        .between(PatrolActionStatistics::getLastPatrolTime, timeVo.getLastCycleStartTime(), timeVo.getLastCycleEndTime())

        );

        // 区域
        lqw.in(CollUtil.isNotEmpty(query.getGroupIds()), PatrolActionStatistics::getGroupId, query.getGroupIds());
        // 门店
        lqw.in(CollUtil.isNotEmpty(query.getStoreIds()),PatrolActionStatistics::getStoreId, query.getStoreIds());

        return lqw;
    }

    private LambdaQueryWrapper<PatrolActionStatistics> buildQueryWrapper(PatrolActionQuery query) {
        LambdaQueryWrapper<PatrolActionStatistics> lqw = Wrappers.lambdaQuery();
        //开始时间,结束时间
        if (ObjectUtil.isNull(query.getStartTime()) && ObjectUtil.isNull(query.getEndTime())) {
            lqw.between(PatrolActionStatistics::getLastPatrolTime, query.getStartTime(), query.getEndTime());
        }
        //区域
        lqw.in(CollectionUtils.isNotEmpty(query.getGroupIds()),PatrolActionStatistics::getGroupId, query.getGroupIds());
        //人员
        lqw.in(CollectionUtils.isNotEmpty(query.getUserIds()),PatrolActionStatistics::getUserId, query.getUserIds());
        return lqw;
    }

    /**
     * 报告按时完成统计
     *
     * @param query
     * @return
     */
    @Override
    public PatrolFinishVo selectReportFinishOnTime(PatrolActionQuery query) {
        List<Long> groupIds = query.getGroupIds();
        if (CollectionUtils.isNotEmpty(groupIds)){
            List<RemoteStoreVo> remoteStoreVos = remoteStoreService.queryStoreByGroupIds(groupIds);
            List<Long> storeIds = remoteStoreVos.stream().map(RemoteStoreVo::getStoreId).collect(Collectors.toList());
            //区域下门店都没有,直接放回
            if (CollectionUtils.isEmpty(storeIds)){
                return new PatrolFinishVo();
            }
            query.setStoreIds(storeIds);
        }
        return baseMapper.selectReportFinishOnTime(query);
    }

    /**
     * 巡店情况统计
     *
     * @param query
     * @return
     */
    @Override
    public PatrolSituationCountVo selectPatrolSituationCount(PatrolActionQuery query) {
        return baseMapper.selectPatrolSituationCount(query);
    }

    @Override
    public List<ProblemRankVo> getProblemRank(StatisticsCountBo bo, StatisticsCountTimeVo timeVo) {
        List<ProblemRankVo> list = baseMapper.getProblemRank(bo, timeVo);
        List<Long> storeIds = list.stream().map(ProblemRankVo::getStoreId).collect(Collectors.toList());
        // 远程调用门店名称
        Map<Long, String> storeMap = remoteStoreService.selectNamesByStoreList(storeIds);
        list.forEach(p-> {
            p.setStoreName(storeMap.getOrDefault(p.getStoreId(), ""));
        });
        return list;
    }

    /**
     * 门店是否覆盖统计
     *
     * @param query
     * @return
     */
    @Override
    public StoreCoverVo selectStoreIsCoveredCount(PatrolActionQuery query) {
        TableDataInfo<StoreCoverVo> coveredDateInfo = this.selectStoreCovered(query);
        long coveredTotal = coveredDateInfo.getTotal();
        TableDataInfo<StoreCoverVo>  notCoveredDateInfo = this.selectStoreNotCovered(query);
        long notCoveredTotal = notCoveredDateInfo.getTotal();
        StoreCoverVo storeCoverVo = new StoreCoverVo();
        storeCoverVo.setStoreCoverNum(coveredTotal);
        storeCoverVo.setStoreNotCoverNum(notCoveredTotal);
        return storeCoverVo;
    }
}
